#include"makeLexemes.h"
//global for GL_possition in string
long GL_pos = 0;
program* syntaxAn(FILE* f)
{
    //setlocale(AL, "ru");
    if(f == NULL)
        {printf("FILE variable is NULL");return NULL;}
    char temp[50];
    char* str = deleteSpacesBuf(f);
    program* pr = (program*) calloc(1, sizeof(program));
    //for analyses of input string
    char ch = 0;
    //for actions in program
    int ppos = 0;
    int mark = 0;
    while(str[GL_pos] != 0)
    {
        if(isdigit(str[GL_pos]))
        {
            pr->lex[ppos].lexType = NUMBER;
            pr->lex[ppos].value   = getN(str);
            ++pr->length;
            ++ppos;
            mark = 1;
        }
        if((ch = isOperator(str)) > 0)
        {
            pr->lex[ppos].lexType = OPERATOR;
            pr->lex[ppos].opType  = ch;
            ++pr->length;
            ++GL_pos;
            ++ppos;
            mark = 1;
        }
        if(isalpha(str[GL_pos]) || str[GL_pos] == '_')
        {
            int i = 0;
            while(isalpha(str[GL_pos]) || str[GL_pos] == '_')
                temp[i++] = str[GL_pos++];
            temp[i] = 0;
            /*if(!strcmp(temp, "конец_моей_любимой_функции_название_выше"))
            {
                pr->lex[ppos].lexType = OPERATOR;
                pr->lex[ppos].opType  = SKIP;
                ppos++;
                ++pr->length;
            }*/
            //next ( for function, else just var;
            if(str[GL_pos] == '(')
                pr->lex[ppos].lexType = FUNCTION;
            else
                pr->lex[ppos].lexType = VARIABLE;
            strcpy(pr->lex[ppos].name, temp);
            ppos++;
            ++pr->length;
            mark = 1;
        }
        if(!mark)
        {
            GL_pos++;
            mark = 0;
        }
    }
    free(str);

    pr->lex[ppos].opType = EOPR;
    pr->lex[ppos].lexType = OPERATOR;
    pr->length++;
    return pr;
}

long fileLength(FILE* f)
{
    if(f == NULL)
        return 0;
    long GL_pos = ftell(f);
    fseek(f, 0, SEEK_SET);
    long length = 0;
    int n = 0;
    while(n != EOF){
        n = fgetc(f);
        ++length;
    }
    fseek(f, GL_pos, SEEK_SET);
    return length;
}

char* deleteSpacesBuf(FILE* f)
{
    if (f == NULL)
        return NULL;
    long currentPossition = ftell(f);
    long len = fileLength(f);
    char* str = (char*) calloc(len, sizeof(char));
    char ch = 0;
    long index = 0;
    ch = getc(f);
    while(ch != EOF)
    {
        if(!(ch == ' ' || ch == '\n' || ch == '\t'))
            str[index++] = ch;
        ch = getc(f);
    }
    fseek(f, currentPossition, SEEK_SET);
    str[index] = 0;
    return str;
}

double getN(char* str)
{
    double n = 0;
    while(isdigit(str[GL_pos]))
    {
        n = n*10 + str[GL_pos] - '0';
        GL_pos++;
    }
    if(str[GL_pos] == '.')
    {
        GL_pos++;
        int decimal = 1;
        double chdec = 0;
        while(isdigit(str[GL_pos]))
        {
            chdec = str[GL_pos] - '0';
            for(int i = 0; i < decimal; i++)
                chdec /= 10;
            ++decimal;
            n += chdec;
            chdec = 0;
            ++GL_pos;
        }
    }
    return n;
}

int isOperator(char* str)
{
    if(str[GL_pos] == '+')
        return ADD;
    if(str[GL_pos] == '*')
        return MUL;
    if(str[GL_pos] == '/')
        return DIV;
    if(str[GL_pos] == '=')
        return MOV;
    if(str[GL_pos] == '|')
        return SKIP;
    if(str[GL_pos] == '!')
        return DEC;
    if(str[GL_pos] == '<' && str[GL_pos+1] == '=')
    {
        GL_pos++;
        return LE;
    }
    else if(str[GL_pos] == '<')
        return LESS;
    if(str[GL_pos] == '>' && str[GL_pos+1] == '=')
    {
        GL_pos++;
        return GE;
    }
    else if(str[GL_pos] == '>')
        return GREATER;
    if(str[GL_pos] == '(')
        return BR_OP;
    if(str[GL_pos] == ')')
        return BR_CL;
    if(str[GL_pos] == ';')
        return OP;
    if(str[GL_pos] == '{')
        return BL_OP;
    if(str[GL_pos] == '}')
        return BL_CL;
    return 0;
    if(str[GL_pos] == '-')
        if(isalpha(str[GL_pos-1]) || isdigit(str[GL_pos-1]))
            return MINUS_BIN;
        else
            return MINUS_UN;
    return 0;
}

int printLexemes(program* pr)
{
    if(pr == NULL)
        return 1;
    printf("LEXEMES: [%d] \n", pr->length);
    for(int i = 0; i < pr->length; i++)
        printf("    [%d] lexType[%d]; opType [%d]; value [%lg]; name <%s>;\n", i, pr->lex[i].lexType, pr->lex[i].opType, pr->lex[i].value, pr->lex[i].name);
}

